﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Reflection;
using P;

namespace Ourmsg.Factory
{
    /// <summary>
    /// 消息对像加工厂
    /// </summary>
    public class XML
    {
        private static System.Text.UTF8Encoding utf8 = new UTF8Encoding();

        private static byte[] NullBytes = new byte[1];

        /// <summary>
        /// 返回对像序列化二进制数组
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static byte[] ConvertToArray(object e)
        {
            string s = ConvertToString(e);
            if (s != null)
                return System.Text.Encoding.UTF8.GetBytes(s);
            else
                return NullBytes;
        }
      
        #region 创建XML消息
        /// <summary>
        /// 创建XML消息
        /// </summary>
        /// <param name="e">Element</param>
        /// <returns></returns>
        public static string ConvertToString(object e)
        {
            if (e == null) return null;
            if (e is P.Message)
            {
                var msg = (P.Message)e;
                ///压缩传输数据
                if (msg.FontName == "宋体") msg.FontName = null;
                if (msg.FontSize == 9) msg.FontSize = 0;
                if (msg.FontColor == -16777216) msg.FontColor = 0;
            }

            MemoryStream fileStream = new MemoryStream();
            XmlTextWriter textWriter = new XmlTextWriter(fileStream, utf8);
            textWriter.WriteStartDocument();
            try
            {
                textWriter.WriteStartElement(e.GetType().ToString());
                PropertyInfo[] propertys = e.GetType().GetProperties();
                foreach (PropertyInfo p in propertys)
                {
                    if (p.GetValue(e, null) == null)
                        continue;

                    if (p.PropertyType == typeof(String) || p.PropertyType == typeof(char)
                        || p.PropertyType == typeof(bool) || p.PropertyType.IsEnum)
                    {

                        var value = p.GetValue(e, null).ToString();
                        if (value != string.Empty && value != "" && value != "False")
                            textWriter.WriteAttributeString(p.Name, value);
                    }
                    if (
                         p.PropertyType == typeof(int)
                        || p.PropertyType == typeof(Single)
                        || p.PropertyType == typeof(float)
                        || p.PropertyType == typeof(byte)
                        || p.PropertyType == typeof(short)
                        || p.PropertyType == typeof(long)
                        || p.PropertyType == typeof(sbyte)
                        || p.PropertyType == typeof(ushort)
                        || p.PropertyType == typeof(uint)
                        || p.PropertyType == typeof(ulong)
                        || p.PropertyType == typeof(double)
                        || p.PropertyType == typeof(decimal)
                        )
                    {
                        var value = p.GetValue(e, null).ToString();
                        if (value != "0")
                            textWriter.WriteAttributeString(p.Name, value);
                    }
                    else if (p.PropertyType == typeof(byte[]))
                    {
                        textWriter.WriteAttributeString(p.Name, Convert.ToBase64String((byte[])p.GetValue(e, null)));
                    }
                    else if (p.PropertyType == typeof(List<object>) && p.GetValue(e, null) != null)
                    { 
                            foreach (Object Obj in (p.GetValue(e, null) as List<object>))
                            {
                                textWriter.WriteStartElement(Obj.GetType().ToString());
                                propertys = Obj.GetType().GetProperties();
                                foreach (PropertyInfo ps in propertys)
                                {
                                    if (ps.GetValue(Obj, null) == null)
                                        continue;

                                    if (ps.PropertyType == typeof(String) || ps.PropertyType == typeof(char)
                                       || ps.PropertyType == typeof(bool) || ps.PropertyType.IsEnum)
                                    {

                                        var value = ps.GetValue(Obj, null).ToString();
                                        if (value != string.Empty && value != "" && value != "False")
                                            textWriter.WriteAttributeString(ps.Name, value);

                                    }
                                    if (
                                         ps.PropertyType == typeof(int)
                                        || ps.PropertyType == typeof(Single)
                                        || ps.PropertyType == typeof(float)
                                        || ps.PropertyType == typeof(byte)
                                        || ps.PropertyType == typeof(short)
                                        || ps.PropertyType == typeof(long)
                                        || ps.PropertyType == typeof(sbyte)
                                        || ps.PropertyType == typeof(ushort)
                                        || ps.PropertyType == typeof(uint)
                                        || ps.PropertyType == typeof(ulong)
                                        || ps.PropertyType == typeof(double)
                                        || ps.PropertyType == typeof(decimal)
                                        )
                                    {
                                        var value = ps.GetValue(Obj, null).ToString();
                                        if (value != "0")
                                            textWriter.WriteAttributeString(ps.Name, value);
                                    }
                                    else if (ps.PropertyType == typeof(byte[]))
                                    {
                                        textWriter.WriteAttributeString(ps.Name, Convert.ToBase64String((byte[])ps.GetValue(Obj, null)));
                                    }
                                }
                                textWriter.WriteEndElement();
                            }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Source + ex.Message);
            }
            textWriter.WriteEndElement();
            textWriter.WriteEndDocument();
            textWriter.Close();

            return System.Text.UTF8Encoding.UTF8.GetString(fileStream.ToArray()).Trim().Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
        }
        #endregion



        #region 从XML中获取一个对像
        /// <summary>
        /// 从XML中获取一个对像 
        /// </summary>
        public static object ConvertToObject(string xmlStr)
        {
            if (xmlStr == null) return null;
            xmlStr = xmlStr.Trim();
            if (xmlStr == "") return null;

            object obj = null;
            try
            {
                XmlReader xmlReader = XmlTextReader.Create(new StringReader(xmlStr));
                if (xmlReader.Read() && xmlReader.NodeType == XmlNodeType.Element)
                {
                    Type ctype = Assembly.GetExecutingAssembly().GetType(xmlReader.Name);
                    obj = System.Activator.CreateInstance(ctype);
                    if (obj == null) return null;

                    PropertyInfo[] propertys = obj.GetType().GetProperties();
                    if (xmlReader.HasAttributes)
                        foreach (PropertyInfo p in propertys)
                        {
                            if (xmlReader.MoveToAttribute(p.Name))
                            {
                                if (p.PropertyType == typeof(String))
                                    p.SetValue(obj, xmlReader.ReadContentAsString(), null);
                                else if (p.PropertyType == typeof(bool))
                                    p.SetValue(obj, bool.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(int))
                                    p.SetValue(obj, int.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(Single))
                                    p.SetValue(obj, Single.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(float))
                                    p.SetValue(obj, float.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType.IsEnum)
                                    p.SetValue(obj, System.Enum.Parse(p.PropertyType, xmlReader.ReadContentAsString(), true), null);
                                else if (p.PropertyType == typeof(short))
                                    p.SetValue(obj, short.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(long))
                                    p.SetValue(obj, long.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(byte))
                                    p.SetValue(obj, byte.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(sbyte))
                                    p.SetValue(obj, sbyte.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(ushort))
                                    p.SetValue(obj, ushort.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(uint))
                                    p.SetValue(obj, uint.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(ulong))
                                    p.SetValue(obj, ulong.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(double))
                                    p.SetValue(obj, double.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(decimal))
                                    p.SetValue(obj, decimal.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(char))
                                    p.SetValue(obj, char.Parse(xmlReader.ReadContentAsString()), null);
                                else if (p.PropertyType == typeof(byte[]))
                                    p.SetValue(obj, Convert.FromBase64String(xmlReader.ReadContentAsString()), null);
                            }
                        }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Source + ex.Message);
            }
            return obj;
        }
        #endregion

         

        #region 从XML中获取所需要的对像(对像在返回值集合中获取)
        /// <summary>
        /// 从XML中获取所需要的对像(对像在返回值集合中获取)
        /// </summary>
        public static List<Object> ConvertToObjects(string xmlStr)
        {
            if (xmlStr == null) return null;
            xmlStr = xmlStr.Trim();
            if (xmlStr == "") return null;

            List<Object> objList = null;
            try
            {
                XmlReader xmlReader = XmlTextReader.Create(new StringReader(xmlStr));
                while (xmlReader.Read())
                    if (xmlReader.NodeType == XmlNodeType.Element)
                    {
                        Type ctype = Assembly.GetExecutingAssembly().GetType(xmlReader.Name);
                        object obj = System.Activator.CreateInstance(ctype);
                        PropertyInfo[] propertys = obj.GetType().GetProperties();
                        if (xmlReader.HasAttributes)
                            foreach (PropertyInfo p in propertys)
                            {
                                if (xmlReader.MoveToAttribute(p.Name))
                                    try
                                    {
                                        if (p.PropertyType == typeof(String))
                                            p.SetValue(obj, xmlReader.ReadContentAsString(), null);
                                        else if (p.PropertyType == typeof(bool))
                                            p.SetValue(obj, bool.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(int))
                                            p.SetValue(obj, int.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(Single))
                                            p.SetValue(obj, Single.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(float))
                                            p.SetValue(obj, float.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType.IsEnum)
                                            p.SetValue(obj, System.Enum.Parse(p.PropertyType, xmlReader.ReadContentAsString(), true), null);
                                        else if (p.PropertyType == typeof(short))
                                            p.SetValue(obj, short.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(long))
                                            p.SetValue(obj, long.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(byte))
                                            p.SetValue(obj, byte.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(sbyte))
                                            p.SetValue(obj, sbyte.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(ushort))
                                            p.SetValue(obj, ushort.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(uint))
                                            p.SetValue(obj, uint.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(ulong))
                                            p.SetValue(obj, ulong.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(double))
                                            p.SetValue(obj, double.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(decimal))
                                            p.SetValue(obj, decimal.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(char))
                                            p.SetValue(obj, char.Parse(xmlReader.ReadContentAsString()), null);
                                        else if (p.PropertyType == typeof(byte[]))
                                            p.SetValue(obj, Convert.FromBase64String(xmlReader.ReadContentAsString()), null);
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.WriteLine(ex.Source + ex.Message);
                                    }
                            }
                        if (objList == null)
                            objList = new List<object>();

                        objList.Add(obj);
                    }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Source + ex.Message);
            }
            return objList;
        }
        #endregion
    }
}
